import os
import matplotlib.pyplot as plt
from flask import Flask, jsonify
from flask import render_template
from flask import request
from tools import DataManage
from urllib import parse

dm = DataManage()  # 初始化一个操作excel的对象

app = Flask(__name__)  # 初始化flask对象

BASE_DIR = os.path.dirname(__file__)  # 获取当前目录


@app.route('/')
def index():
    """
    登录页
    :return:
    """
    return render_template('login.html')  # 利用flask的render_template函数，把跟路径/引到login.html页面上


@app.route('/home/')
def home():
    """
    首页
    :return:
    """
    return render_template('dataManager.html')  # 利用flask的render_template函数，把跟路径/引到dataManager.html页面上


@app.route('/log_in/', methods=['POST'])
def login():
    """
    登录判断
    :return:
    """
    user_name = request.form.get('username')  # 获取从前端传过来的用户名
    password = request.form.get('password')  # 获取从前端传过来的密码
    if user_name == 'admin':  # 判断是否是admin账号
        if password == '123456':  # 判断密码，当前写死为123456
            return render_template('dataManager.html')  # 引到dataManager.html页面上
        else:
            return render_template('login.html', msg='密码错误，请重新输入') # 登录失败，返回登录页，并给出提示
    else:
        return render_template('login.html', msg='请使用admin进行登录！') # 登录失败，返回登录页，并给出提示


@app.route('/add/', methods=['POST'])
def add_score():
    """
    新增学生成绩
    :return:
    """
    # 接收前端传过来的参数，这些参数是html中form表单定义好的
    college = request.form.get('college')  # 获取从前端传过来的学院
    if not college:  # 判断学院不能为空
        return render_template('dataManager.html', msg='学院不能为空！')
    major = request.form.get('major')# 获取从前端传过来的专业
    if not major:# 判断学院不能为空
        return render_template('dataManager.html', msg='专业不能为空！')
    t_lass = request.form.get('t_lass')# 获取从前端传过来的班级
    if not t_lass:# 判断学院不能为空
        return render_template('dataManager.html', msg='班级不能为空！')
    stu_card = request.form.get('stu_card')# 获取从前端传过来的卡号
    if not stu_card:# 判断学院不能为空
        return render_template('dataManager.html', msg='卡号不能为空！')
    stu_name = request.form.get('stu_name')# 获取从前端传过来的姓名
    if not stu_name:# 判断学院不能为空
        return render_template('dataManager.html', msg='姓名不能为空！')
    course = request.form.get('course')# 获取从前端传过来的课程
    if not course:# 判断学院不能为空
        return render_template('dataManager.html', msg='课程不能为空！')
    score = request.form.get('score')# 获取从前端传过来的分数
    if not score:# 判断学院不能为空
        return render_template('dataManager.html', msg='分数不能为空！')

    # 调用数据操作对象的add_data函数，把新数据存入到excel文件中
    dm.add_data(college, major, t_lass, stu_card, stu_name, course, score)
    return render_template('dataManager.html', msg='新增数据成功！')


@app.route('/modify/', methods=['POST'])
def modify_score():
    """
    修改学生成绩
    :return:
    """
    # 接收前端传过来的参数，这些参数是html中form表单定义好的
    college = request.form.get('college')# 获取从前端传过来的学院
    major = request.form.get('major')# 获取从前端传过来的专业
    t_lass = request.form.get('t_lass')# 获取从前端传过来的班级
    stu_card = request.form.get('stu_card')# 获取从前端传过来的学号
    stu_name = request.form.get('stu_name')# 获取从前端传过来的姓名
    course = request.form.get('course')# 获取从前端传过来的课程
    score = request.form.get('score')# 获取从前端传过来的分数
    result = dm.data_frame.query('学院=="{}" & 专业=="{}" & 班级=="{}" & 学号=={} & 姓名=="{}" & 课程=="{}"'.format(  # 利用pandas的query函数进行过滤，条件为前端传过来的参数
        college, major, t_lass, stu_card, stu_name, course
    ))
    dm.data_frame.loc[result.index.values[0], '分数'] = score # 设置最新的分数
    dm.save_data()  # 保存数据
    return render_template('dataManager.html', msg='修改数据成功！')


@app.route('/delete/', methods=['POST'])
def delete_score():
    """
    删除学生成绩
    :return:
    """
    params = parse.unquote(request.data.decode('utf8')) #url编码成正常的中文
    params = params.split('&')# 分解数据为单独的 xxx=aaa，然后再进行解析
    for pa in params:
        if 'college' in pa:
            college = pa.replace('college=', '') # 替换无用的college=字符串
        if 'major' in pa:
            major = pa.replace('major=', '')# 替换无用的major=字符串
        if 't_lass' in pa:
            t_lass = pa.replace('t_lass=', '')# 替换无用的t_lass=字符串
        if 'stu_card' in pa:
            stu_card = pa.replace('stu_card=', '')# 替换无用的stu_card=字符串
        if 'stu_name' in pa:
            stu_name = pa.replace('stu_name=', '')# 替换无用的stu_name=字符串
        if 'course' in pa:
            course = pa.replace('course=', '')# 替换无用的course=字符串
    # 接收前端传过来的参数，这些参数是html中form表单定义好的

    result = dm.data_frame.query('学院=="{}" & 专业=="{}" & 班级=="{}" & 学号=={} & 姓名=="{}" & 课程=="{}"'.format(# 利用pandas的query函数进行过滤，条件为前端传过来的参数
        college, major, t_lass, stu_card, stu_name, course
    ))
    dm.data_frame.drop(dm.data_frame.index[result.index[0]], inplace=True)# 删除数据
    dm.save_data()#更新数据到文件中
    dm.read_data()#重新读取最新的数据
    return jsonify({'msg': '删除数据成功！'})#返回结果


@app.route('/scores/', methods=['GET'])
def get_score():
    """
    获取所有学生成绩
    :return:
    """
    sort = request.args.get('sorted', None)  # 默认按照存储的顺序显示，如果是up 则升序，down 则倒序
    # 调用数据操作对象的read_data函数，把数据读取出来
    datas = dm.read_data()
    # 把数据转化为python的list对象
    datas = datas.values.tolist()
    # 循环一遍数据，返回给前端进行使用
    new_datas = []
    for data in datas:
        _tmp = {# 给每个数据进行命名，方便前端调用
            'college': data[0], 'major': data[1], 't_lass': data[2], 'stu_card':data[3], 'stu_name': data[4],
            'course': data[5], 'score': data[6]
        }
        new_datas.append(_tmp)
    new_datas = new_datas[::-1]#d倒叙排序，后增加的数据优先在前面显示
    # 实现排序功能
    if sort == 'up':  # 升序
        new_datas = sorted(new_datas, key=lambda e: e['score'], reverse=False)
    if sort == 'down':  # 倒序
        new_datas = sorted(new_datas, key=lambda e: e['score'], reverse=True)
    return jsonify({'datas': new_datas})


@app.route('/analysis_index/', methods=['GET'])
def analysis_index():
    """
    分析的首页
    """
    return render_template('analysis.html')


@app.route('/analysis/', methods=['GET'])
def analysis_score():
    """
    分析学生成绩，整理到饼图中
    :return:
    """
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签

    # 调用数据操作对象的read_data函数，把数据读取出来
    datas = dm.read_data()
    # 把数据转化为python的list对象
    new_datas = datas.values.tolist()

    # 分析学院学生人数 -- 柱形图
    college_data = {}
    # 分析整体及格情况 -- 饼图
    pass_and_fail = {'pass': 0, 'fail': 0}
    # 成绩分布情况 -- 饼图
    score_data = {
        '0~29': 0,
        '30~59': 0,
        '60~79': 0,
        '80~100': 0
    }
    for data in new_datas:
        # 统计学院的学生人数
        if data[0] not in college_data:
            college_data[data[0]] = 1  # 如果不存在，初始化这个学院的数据
        else:
            college_data[data[0]] += 1 # 如果存在，则新增一条数据
        # 统计及格和不及格情况
        if data[6] >= 60:
            pass_and_fail['pass'] += 1
        else:
            pass_and_fail['fail'] += 1
        # 统计成绩分布情况
        if 0 < data[6] <= 29:
            score_data['0~29'] += 1
        if 29 < data[6] <= 59:
            score_data['30~59'] += 1
        if 59 < data[6] <= 79:
            score_data['60~79'] += 1
        if 79 < data[6] <= 100:
            score_data['80~100'] += 1

    # 生成统计学院的学生人数图形
    print(college_data)
    data_X = college_data.keys()#设置x轴
    data_Y = college_data.values()#设置y轴
    plt.title("学院学生人数统计")#设置标题
    plt.bar(data_X, data_Y)#生成柱形图

    plt.savefig('static/college_data.jpg')#保存图片到本地中
    plt.close()#关闭，防止后面图形重叠

    # 生成统计学院的学生人数图形
    print(pass_and_fail)
    labels = ['及格', '不及格']#设置显示标签
    sizes = pass_and_fail.values()#设置饼图数据
    explode = (0, 0.1)#设置第二个范围图突出
    plt.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=False, startangle=150)#生成饼图
    plt.title("学生成绩及格人数统计")#设置标题
    plt.savefig('static/pass_and_fail.jpg')#保存图片至本地
    plt.close()#关闭，防止后面图形重叠

    # 生成成绩分布图
    print(score_data)
    labels = score_data.keys()#设置显示标签
    sizes = score_data.values()#设置饼图数据
    explode = (0, 0, 0.1, 0)#设置第三个范围图突出
    plt.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=False, startangle=150)#生成饼图
    plt.title("成绩分布图统计")#设置标题
    plt.savefig('static/score_data.jpg')#保存图片至本地
    plt.close()#关闭，防止后面图形重叠
    # 返回对应的结果图片给前端进行展示
    return jsonify({'data': {#返回结果给前端
        'score_data': 'analysis/score_data.jpg',
        'pass_and_fail': 'analysis/pass_and_fail.jpg',
        'college_data': 'analysis/college_data.jpg',
    }, 'msg': '分析成功！'})


if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5001)

